#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os
import sys
from mutagen.mp3 import MP3
from mutagen.id3 import ID3

# 统计信息
stats = {
    'renamed': [],
    'skipped': [],
    'passed': [],
    'error': [],
    'samename': [],
}

def sanitize_filename(name):
    """移除文件名中不允许的字符"""
    invalid = '<>:"/\\|?*'
    for ch in invalid:
        name = name.replace(ch, '_')
    # 可选：去除首尾空格和点（避免 . 开头的隐藏文件或无效名）
    name = name.strip().strip('.')
    return name

def rename_by_tag(filepath):
    global stats
    try:
        audio = MP3(filepath, ID3=ID3)
    except Exception as e:
        stats['error'].append((filepath, f"无法读取: {e}"))
        return

    if audio.tags is None:
        stats['skipped'].append((filepath, "无 ID3 标签"))
        return

    # 获取标题和艺术家（直接使用 str()，假设已是 UTF-8）
    title = str(audio.tags.get('TIT2', '')).strip() if 'TIT2' in audio.tags else ''
    artist = str(audio.tags.get('TPE1', '')).strip() if 'TPE1' in audio.tags else ''

    if not title:
        stats['skipped'].append((filepath, "无歌名（TIT2）"))
        return

    # 构建新文件名
    if artist:
        new_basename = f"{artist} - {title}"
    else:
        new_basename = title

    new_basename = sanitize_filename(new_basename)
    new_filepath = os.path.join(os.path.dirname(filepath), new_basename + ".mp3")

    # 避免覆盖：如果目标已存在，加后缀
    counter = 1
    original_new = new_filepath
    while os.path.exists(new_filepath) and os.path.realpath(new_filepath) != os.path.realpath(filepath):
        name, ext = os.path.splitext(original_new)
        new_filepath = f"{name}_{counter}{ext}"
        counter += 1
    
    if original_new != new_filepath:
        stats['samename'].append(new_filepath)

    # 如果新路径和原路径相同（比如文件名本来就是“歌手-歌名.mp3”），跳过重命名
    if os.path.normcase(os.path.abspath(new_filepath)) == os.path.normcase(os.path.abspath(filepath)):
        stats['passed'].append(filepath)
        return

    try:
        os.rename(filepath, new_filepath)
        stats['renamed'].append((filepath, new_filepath))
    except Exception as e:
        stats['error'].append((filepath, f"重命名失败: {e}"))

def print_summary():
    print("\n" + "="*40 + " [Summary] " + "="*40)

    print(f"成功: {len(stats['renamed']):>5}")
    print(f"忽略: {len(stats['passed']):>5}")
    print(f"同名: {len(stats['samename']):>5}")
    stats['samename'].sort()
    for fp in stats['samename']:
        print(f"  - {fp}")
    print(f"跳过: {len(stats['skipped']):>5}")
    for fp, reason in stats['skipped']:
        print(f"  - {fp} | {reason}")

    print(f"错误: {len(stats['error']):>5}")
    for fp, err in stats['error']:
        print(f"  - {fp} | 错误: {err}")

    total = len(stats['renamed']) + len(stats['skipped']) + len(stats['passed']) + len(stats['error'])
    print("\n" + "-"*20)
    print(f"总计: {total:>5}")

def main():
    if len(sys.argv) != 2:
        print("用法: python rename_mp3_by_tag.py <mp3 file or directory>")
        print("功能: 根据 ID3 标签重命名 MP3 文件为「歌手-歌名.mp3」或「歌名.mp3」")
        return

    path = sys.argv[1]

    if os.path.isfile(path):
        if path.lower().endswith('.mp3'):
            rename_by_tag(path)
        else:
            print("ERROR: 输入文件不是 MP3 文件")
    elif os.path.isdir(path):
        for root, _, files in os.walk(path):
            for f in files:
                if f.lower().endswith('.mp3'):
                    rename_by_tag(os.path.join(root, f))
    else:
        print("ERROR: 路径不存在")
        return

    print_summary()

if __name__ == "__main__":
    main()
